package com.tool.payment.util;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;

/**
 * 利用zxing开源工具生成二维码QRCode
 * 
 * @date 2012-10-26
 * @author xhw
 * 
 */
public class QRUtil {
	
    private static final int BLACK = 0xff000000;
    private static final int WHITE = 0xFFFFFFFF;
    
	private static final Logger logger = LoggerFactory.getLogger(QRUtil.class);
    
    /**
     * 生成QRCode二维码<br> 
     */
    public static void createQRcode(String contents, String file, String logo, int width) {
    	try {
    		Map<EncodeHintType, Object> hints = new HashMap<>();  
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            hints.put(EncodeHintType.MARGIN, 1);
    		BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, 
    									BarcodeFormat.QR_CODE, width, width, hints);
    		writeToFile(bitMatrix, "png", file, logo); 
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    }
    
    public static InputStream createQRcode(String contents,String logo,int width) {
    	try {
    		Map<EncodeHintType, Object> hints = new HashMap<>();  
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            hints.put(EncodeHintType.MARGIN, 1);
    		BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, 
    									BarcodeFormat.QR_CODE, width, width, hints);
    		return writeToInputStream(bitMatrix, "png", logo);
    	} catch (Exception e) {
    		e.printStackTrace();
    	}
    	return null;
    }
    
    /**
     * 生成QRCode二维码<br> 
     */
    public static void createQRcode(String contents, String logo, int width, HttpServletResponse response){
        try {
        	Map<EncodeHintType, Object> hints = new HashMap<>();  
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            hints.put(EncodeHintType.MARGIN, 1);
            BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, 
            						BarcodeFormat.QR_CODE, width, width,hints);
            writeToPage(bitMatrix, "png", logo, response);
        } catch (Exception e) {
        	logger.info("e.message:"+e.getMessage());
            e.printStackTrace();
        }
    }
    
    /**
     * 生成二维码图片<br>
     * 
     * @param matrix
     * @param format 图片格式
     * @throws IOException
     */
    private static void writeToPage(BitMatrix matrix, String format, String logo, HttpServletResponse response) throws IOException {
        BufferedImage image = toBufferedImage(matrix,logo);
        ImageIO.write(image, format, response.getOutputStream());
    }
    
    
    /**
     * 生成二维码图片<br>
     * 
     * @param matrix
     * @param format 图片格式
     * @param file 生成二维码图片位置
     * @throws IOException
     */
    private static void writeToFile(BitMatrix matrix, String format, String filepath, String logo) throws IOException {
        BufferedImage image = toBufferedImage(matrix, logo);
        ImageIO.write(image, format, new File(filepath));
    }
    
    /**
     * 生成二维码流
     * @param matrix
     * @param format
     * @param logo
     * @return
     */
    private static InputStream writeToInputStream(BitMatrix matrix, String format, String logo) {
    	 InputStream is = null; 
    	try {
    		BufferedImage image = toBufferedImage(matrix, logo);
        	//创建储存图片二进制流的输出流
        	ByteArrayOutputStream baos = new ByteArrayOutputStream();
        	//创建ImageOutputStream流
        	ImageOutputStream imageOutputStream = ImageIO.createImageOutputStream(baos);
        	//将二进制数据写进ByteArrayOutputStream
        	ImageIO.write(image, format, imageOutputStream);
        	
        	is= new ByteArrayInputStream(baos.toByteArray()); 
		} catch (Exception e) {
			
		}
    	return is;
    }

    /**
     * 生成二维码内容<br>
     * 
     * @param matrix
     * @return
     */
    private static BufferedImage toBufferedImage(BitMatrix matrix, String logo) {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, matrix.get(x, y) == true ? BLACK : WHITE);
            }
        }
        if(logo != null) {
        	return addLogo(image,logo);
        }
        return image;
    }
    /**
     * 增加logo
     * @param qrcodeImage
     * @param logopath
     * @return
     */
    private static BufferedImage addLogo(BufferedImage qrcodeImage, String logopath) {
    	Graphics2D g = null;
    	try {
            Image logoImage = zoomImage(logopath);
            int deltaHeight = qrcodeImage.getHeight() - logoImage.getHeight(null);
            int deltaWidth = qrcodeImage.getWidth() - logoImage.getWidth(null);

            g = qrcodeImage.createGraphics();
            g.drawImage(logoImage, (int) Math.round(deltaWidth / 2), (int) Math.round(deltaHeight / 2), null);
        } catch (Exception e) {
        	logger.info("生成带logo的二维码失败",e);
        } finally {
        	if(g != null) {
        		g.dispose();
        	}
        }
        return qrcodeImage;
    }

    /**
     * 缩放图片
     * @param logopath
     * @return
     */
    private static Image zoomImage(String logopath) {
    	 BufferedImage logoImage = null;
		try {
			logoImage = ImageIO.read(new URL(logopath));
		} catch (IOException e) {
			logger.info("读取图片失败",e);
			try {
				logoImage = ImageIO.read(new File(logopath));
			} catch (IOException e1) {
				logger.info("读取图片失败",e);
			}
		}
		//缩放
		int logoWigth = 100;
		int logoHeight =  logoImage.getHeight(null)*logoWigth/logoImage.getWidth(null);
		Image image =logoImage.getScaledInstance(logoWigth, logoHeight, Image.SCALE_SMOOTH);//缩小
		return image;
    }
    
    public static void main(String[] args) {
        String file = "D://test16.png";
        String logopath = "D://test1.png";
//        String logopath = "http://wx.qlogo.cn/mmopen/ARdlqiah49Dzddt8CODZqhdx3unWXzgzh4bglLnggRBAKSv7f9nLpRKfQRsABPhLE9cHNo7NW9d7bAPWha1fZobFXQFTWj7eR/0";
//        test.encode("weixin://wxpay/bizpayurl?pr=xfWRHmx", file, BarcodeFormat.QR_CODE, 200,200, null);
        QRUtil.createQRcode("http://www.baidu.com", file,logopath, 500);
    }
}